package com.bf.electroplating.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bf.electroplating.pojo.entity.ComWorkshop;
import com.bf.electroplating.pojo.entity.PubAttachment;
import com.bf.electroplating.pojo.entity.PubAttachmentRel;
import com.bf.electroplating.pojo.enums.AttModuleEnums;
import com.bf.electroplating.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.UUID;

/**
 * 车间数据迁移服务实现类
 * 用于将车间信息及其附件从一个数据库的MinIO迁移到另一个数据库的MinIO
 */
@Slf4j
@Service
public class WorkshopDataMigrationServiceImpl {

    @Resource
    private ComWorkshopService comWorkshopService;

    @Resource
    private PubAttachmentService pubAttachmentService;

    @Resource
    private PubAttachmentRelService pubAttachmentRelService;

    @Value("${system.endpoint:}")
    private String sourceMinioEndpoint;

    @Value("${system.bucketName:}")
    private String sourceMinioBucket;

    @Value("${migration.target.minio.endpoint:}")
    private String targetMinioEndpoint;

    @Value("${migration.target.minio.bucket:}")
    private String targetMinioBucket;

    /**
     * 迁移所有车间数据及其附件
     */
    @Transactional(rollbackFor = Exception.class)
    public void migrateAllWorkshopData() {
        log.info("开始迁移所有车间数据");

        // 获取所有车间数据
        List<ComWorkshop> workshops = comWorkshopService.list();
        log.info("找到{}个车间需要迁移", workshops.size());

        int successCount = 0;
        int failCount = 0;

        for (ComWorkshop workshop : workshops) {
            try {
                migrateWorkshopData(workshop);
                successCount++;
                log.info("车间数据迁移成功：{}", workshop.getWorkshopName());
            } catch (Exception e) {
                failCount++;
                log.error("车间数据迁移失败：{}，错误：{}", workshop.getWorkshopName(), e.getMessage(), e);
            }
        }

        log.info("车间数据迁移完成，成功：{}，失败：{}", successCount, failCount);
    }

    /**
     * 迁移单个车间数据及其附件
     */
    @Transactional(rollbackFor = Exception.class)
    public void migrateWorkshopData(ComWorkshop workshop) {
        log.info("开始迁移车间数据：{}", workshop.getWorkshopName());

        // 1. 迁移车间基本信息（如果需要的话）
        // 这里假设车间基本信息已经在目标数据库中，只需要迁移附件

        // 2. 迁移车间附件
        migrateWorkshopAttachments(workshop.getId(), AttModuleEnums.WORKSHOP.getCode());

        // 3. 迁移平面图附件
        migrateWorkshopAttachments(workshop.getId(), AttModuleEnums.FLOOR_PLAN.getCode());

        // 4. 迁移现场照片附件
        migrateWorkshopAttachments(workshop.getId(), AttModuleEnums.SCENE.getCode());

        // 5. 迁移环评章节附件
        migrateWorkshopAttachments(workshop.getId(), AttModuleEnums.EIA_CHAPTER.getCode());

        log.info("车间数据迁移完成：{}", workshop.getWorkshopName());
    }

    /**
     * 迁移指定类型的车间附件
     */
    private void migrateWorkshopAttachments(String workshopId, String attachmentType) {
        log.info("开始迁移车间附件，车间ID：{}，附件类型：{}", workshopId, attachmentType);

        // 获取源数据库中的附件关系
        List<PubAttachmentRel> attachmentRels = pubAttachmentRelService.list(
                new LambdaQueryWrapper<PubAttachmentRel>()
                        .eq(PubAttachmentRel::getRelationId, workshopId)
                        .eq(PubAttachmentRel::getStorePath, attachmentType)
        );

        if (attachmentRels.isEmpty()) {
            log.info("车间ID：{}，附件类型：{}，没有找到附件", workshopId, attachmentType);
            return;
        }

        // 获取附件详细信息
        List<String> attachmentIds = attachmentRels.stream()
                .map(PubAttachmentRel::getAttId)
                .collect(java.util.stream.Collectors.toList());

        List<PubAttachment> attachments = pubAttachmentService.listByIds(attachmentIds);

        // 迁移每个附件
        for (PubAttachment attachment : attachments) {
            try {
                migrateSingleAttachment(workshopId, attachmentType, attachment);
            } catch (Exception e) {
                log.error("附件迁移失败，附件ID：{}，错误：{}", attachment.getId(), e.getMessage(), e);
            }
        }
    }

    /**
     * 迁移单个附件
     */
    private void migrateSingleAttachment(String workshopId, String attachmentType, PubAttachment sourceAttachment) {
        log.info("开始迁移附件：{}", sourceAttachment.getSourceName());

        try {
            // 1. 从源MinIO下载文件
            byte[] fileData = downloadFileFromSourceMinio(sourceAttachment.getStorePath());

            // 2. 创建MultipartFile对象用于上传
            MultipartFile multipartFile = createMultipartFile(
                    sourceAttachment.getSourceName(),
                    sourceAttachment.getFileType(),
                    fileData
            );

            // 3. 调用远程服务器更新附件
            String result = pubAttachmentService.uploadFileToTargetMinio(multipartFile, attachmentType, sourceAttachment.getId());
            
            if ("success".equals(result)) {
                log.info("远程附件更新成功：{}", sourceAttachment.getSourceName());
            } else {
                log.error("远程附件更新失败：{}，结果：{}", sourceAttachment.getSourceName(), result);
                throw new RuntimeException("远程附件更新失败：" + result);
            }

        } catch (Exception e) {
            log.error("附件迁移失败：{}，错误：{}", sourceAttachment.getSourceName(), e.getMessage(), e);
            throw new RuntimeException("附件迁移失败", e);
        }
    }

    /**
     * 从源MinIO下载文件
     */
    private byte[] downloadFileFromSourceMinio(String filePath) throws IOException {
        try {
            // 构建源MinIO的完整URL
            String fullUrl = sourceMinioEndpoint + "/" + sourceMinioBucket + "/" + filePath;

            URL url = new URL(fullUrl);
            URLConnection connection = url.openConnection();

            try (InputStream inputStream = connection.getInputStream()) {
                return inputStream.readAllBytes();
            }
        } catch (Exception e) {
            log.error("从源MinIO下载文件失败：{}", filePath, e);
            throw new IOException("下载文件失败", e);
        }
    }

    /**
     * 上传文件到目标MinIO
     */
    private String uploadFileToTargetMinio(MultipartFile file, String attachmentType, String id) {
        try {
            // 使用现有的附件服务上传文件
            // 这里需要调用目标数据库的附件上传服务
            return pubAttachmentService.uploadFileToTargetMinio(file, attachmentType,id);
        } catch (Exception e) {
            log.error("上传文件到目标MinIO失败：{}", file.getOriginalFilename(), e);
            throw new RuntimeException("上传文件失败", e);
        }
    }

    /**
     * 创建MultipartFile对象
     */
    private MultipartFile createMultipartFile(String fileName, String contentType, byte[] data) {
        return new MultipartFile() {
            @Override
            public String getName() {
                return "file";
            }

            @Override
            public String getOriginalFilename() {
                return fileName;
            }

            @Override
            public String getContentType() {
                return contentType;
            }

            @Override
            public boolean isEmpty() {
                return data == null || data.length == 0;
            }

            @Override
            public long getSize() {
                return data.length;
            }

            @Override
            public byte[] getBytes() throws IOException {
                return data;
            }

            @Override
            public InputStream getInputStream() throws IOException {
                return new ByteArrayInputStream(data);
            }

            @Override
            public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
                throw new UnsupportedOperationException("transferTo not supported");
            }
        };
    }

    /**
     * 创建目标附件记录
     */
    private PubAttachment createTargetAttachment(PubAttachment sourceAttachment, String newFilePath) {
        PubAttachment targetAttachment = new PubAttachment();
        targetAttachment.setId(UUID.randomUUID().toString());
        targetAttachment.setFileType(sourceAttachment.getFileType());
        targetAttachment.setDelFlag("0");

        return targetAttachment;
    }

    /**
     * 验证迁移结果
     */
    public void validateMigrationResult(String workshopId) {
        log.info("开始验证迁移结果，车间ID：{}", workshopId);

        // 验证各种类型的附件是否迁移成功
        String[] attachmentTypes = {
                AttModuleEnums.WORKSHOP.getCode(),
                AttModuleEnums.FLOOR_PLAN.getCode(),
                AttModuleEnums.SCENE.getCode(),
                AttModuleEnums.EIA_CHAPTER.getCode()
        };

        for (String attachmentType : attachmentTypes) {
            List<PubAttachmentRel> attachmentRels = pubAttachmentRelService.list(
                    new LambdaQueryWrapper<PubAttachmentRel>()
                            .eq(PubAttachmentRel::getRelationId, workshopId)
                            .eq(PubAttachmentRel::getStorePath, attachmentType)
            );

            log.info("附件类型：{}，迁移数量：{}", attachmentType, attachmentRels.size());
        }
    }
}
